package sf.database.jdbc.type;

import sf.tools.StringUtils;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Struct;
import java.sql.Types;

public class StructType implements TypeHandler<Struct> {
    /**
     * struct的类型名称(oracle支持)
     */
    private String typeName;

    public StructType(String typeName) {
        this.typeName = typeName;
    }

    public StructType() {
    }

    public Struct get(ResultSet rs, String colName) throws SQLException {
        Object obj = rs.getObject(colName);
        return getValue(obj);
    }


    public Struct get(ResultSet rs, int index) throws SQLException {
        Object obj = rs.getObject(index);
        return getValue(obj);
    }

    @Override
    public Struct get(CallableStatement cs, int index) throws SQLException {
        Object obj = cs.getObject(index);
        return getValue(obj);
    }

    @Override
    public Struct get(CallableStatement cs, String parameterName) throws SQLException {
        Object obj = cs.getObject(parameterName);
        return getValue(obj);
    }

    private Struct getValue(Object obj) {
        if (obj == null) {
            return null;
        } else {
            return (Struct) obj;
        }
    }

    @Override
    public void update(ResultSet rs, String columnLabel, Object value) throws SQLException {
        if (value instanceof Struct) {
            rs.updateObject(columnLabel, value);
        } else if (StringUtils.isNotBlank(typeName) && value instanceof Object[]) {
            Struct struct = rs.getStatement().getConnection().createStruct(typeName, (Object[]) value);
            rs.updateObject(columnLabel, struct);
        }
    }

    @Override
    public void update(ResultSet rs, int columnIndex, Object value) throws SQLException {
        if (value instanceof Struct) {
            rs.updateObject(columnIndex, value);
        } else if (StringUtils.isNotBlank(typeName) && value instanceof Object[]) {
            Struct struct = rs.getStatement().getConnection().createStruct(typeName, (Object[]) value);
            rs.updateObject(columnIndex, struct);
        }
    }

    public Object set(PreparedStatement stat, Object obj, int i) throws SQLException {
        if (null == obj) {
            stat.setNull(i, getSqlType());
        } else if (obj instanceof Struct) {
            stat.setObject(i, obj);
        } else if (StringUtils.isNotBlank(typeName) && obj instanceof Object[]) {
            Struct struct = stat.getConnection().createStruct(typeName, (Object[]) obj);
            stat.setObject(i, struct);
        }
        return null;
    }

    @Override
    public Object set(CallableStatement cs, Object obj, String parameterName) throws SQLException {
        if (null == obj) {
            cs.setNull(parameterName, getSqlType());
        } else if (obj instanceof Struct) {
            cs.setObject(parameterName, obj);
        } else if (StringUtils.isNotBlank(typeName) && obj instanceof Object[]) {
            Struct struct = cs.getConnection().createStruct(typeName, (Object[]) obj);
            cs.setObject(parameterName, struct);
        }
        return null;
    }

    @Override
    public int getSqlType() {
        return Types.STRUCT;
    }

    @Override
    public Class<Struct> getDefaultJavaType() {
        return Struct.class;
    }

    public String getTypeName() {
        return typeName;
    }

    public void setTypeName(String typeName) {
        this.typeName = typeName;
    }
}
